热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

波形|节拍_fpga实操训练(ipram和ipfifo)

篇首语:本文由编程笔记#小编为大家整理,主要介绍了fpga实操训练(ipram和ipfifo)相关的知识,希望对你有一定的参考价值。【声明:版权所有&

篇首语:本文由编程笔记#小编为大家整理,主要介绍了fpga实操训练(ip ram和ip fifo)相关的知识,希望对你有一定的参考价值。


【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】


        所有的fpga ip当中,用的最多的ip一般有pll、rom、ram和fifo。前面,我们讨论过了rom,rom相比较ram和fifo而言,多一个mif文件的配置。而ram、fifo则不需要这样的操作。今天可以继续学习下ram和fifo,这样在后面的开发中就会显得游刃有余。


1、ip ram配置

a)创建ip ram的方法

        要创建ip ram,首先需要打开ip catalog,输入ram,选择双端口输入,

         接下来,系统会提示输入文件名,不妨命名为ip_ram.v。完成命名之后,就可以开始ip的配置了。这里面有几个重要的对话框需要注意下,首先是设置好bit宽度和word数量,

        确认是否共享时钟,

         确认是否需要晚一节拍输出数据,

         其他部分的页面采用默认的配置就可以了。


b)准备测试代码

        有了ip ram核之后,下面就是需要把它实例化,并且添加必要的测试代码。内容如下所示,

module top(clk, rst);
input clk;
input rst;
wire clk;
wire rst;
reg[4:0] read_address;
reg[4:0] write_address;
reg[7:0] write_data;
reg write_en;
wire[7:0] read_data;
always@(posedge clk or negedge rst)
if(!rst)
read_address <&#61; 5&#39;d0;
else
read_address <&#61; read_address &#43; 1&#39;b1;
always&#64;(posedge clk or negedge rst)
if(!rst) begin
write_en <&#61; 1&#39;b0;
write_address <&#61;5&#39;d0;
write_data <&#61; 8&#39;d0;
end else begin
if(write_address !&#61; 5&#39;d31) begin
write_en <&#61; 1&#39;b1;
write_address <&#61; write_address &#43; 1&#39;b1;
write_data <&#61; write_data &#43; 8&#39;d2 ;
end else begin
write_en <&#61; 1&#39;b0;
write_address <&#61;5&#39;d0;
write_data <&#61; 8&#39;d0;
end
end
ip_ram ip_ram0(
.clock(clk),
.data(write_data),
.rdaddress(read_address),
.wraddress(write_address),
.wren(write_en),
.q(read_data)
);
endmodule

         测试的代码逻辑并不复杂。首先&#xff0c;在fpga复位之后&#xff0c;先对ram进行赋值操作。等所有的地址都写上数据之后&#xff0c;下面就是不停循环读出这些数据。为了验证这些数据是否真的被写入到ram空间&#xff0c;可以通过SignalTap的方法&#xff0c;通过jtag读一下这些数据&#xff0c;观察之前的写操作究竟有没有生效。


c&#xff09;准备SignalTap&#xff0c;并且开始测试

        SignalTap的配置方法前面提过多次&#xff0c;这里直接给出配置的截图即可&#xff0c;

         经过输入F6和Esc之后&#xff0c;就可以看到截取的地址和数据了&#xff0c;

         前面编写测试代码的时候&#xff0c;写入的数据都是address*2。假设输入的地址是0&#xff0c;那么读取的数据应该是0&#xff1b;如果输入的地址是1&#xff0c;那么读取的数据应该是2&#xff0c;依次类推。通过截图&#xff0c;我们发现当read_address是0x12h的时候&#xff0c;q需要等一个时钟才能输出0x24h。这说明&#xff0c;ram和rom其实是一样的&#xff0c;两者都是等一个时钟才能输出数据的。


2、ip fifo配置

a&#xff09;和ram一样&#xff0c;首先还是从ip catalog中寻找fifo&#xff0c;

        同样&#xff0c;这里需要用户自己输入文件名。不妨命名为ip_fifo.v&#xff0c;接着就可以开始配置。配置的内容很多&#xff0c;最关键的有这么几处。首先&#xff0c;输入write bit长度、read bit长度、总长度。这个非常有用&#xff0c;

         确定主要的输出信号&#xff0c;

         确认rdreq的用法&#xff0c;

         完成主要的这些操作之后&#xff0c;再加上自身的默认配置&#xff0c;就可以完成ip fifo的基本设定了。


b&#xff09;准备测试代码

module top(clk, rst);
input clk;
input rst;
wire clk;
wire rst;
reg[7:0] write_data;
wire[31:0] read_data;
wire write_full;
wire read_empty;
reg write_req;
reg read_req;
// write state and next_write_state
reg[1:0] write_state;
reg[1:0] next_write_state;
always&#64;(posedge clk or negedge rst)
if(!rst)
write_state <&#61; 2&#39;b00;
else
write_state <&#61; next_write_state;

always&#64;(*)
if(!rst)
next_write_state <&#61; 2&#39;b00;
else begin
case (write_state)
2&#39;b00:
if(!write_full)
next_write_state <&#61; 2&#39;b01;
else
next_write_state <&#61; 2&#39;b00;

2&#39;b01:
if(write_full)
next_write_state <&#61; 2&#39;b00;
else
next_write_state <&#61; 2&#39;b01;

default:
next_write_state <&#61; 2&#39;b00;
endcase
end
always &#64;(posedge clk or negedge rst)
if(!rst)
write_req <&#61; 1&#39;b0;
else if(next_write_state &#61;&#61; 2&#39;b01)
write_req <&#61; 1&#39;b1;
else
write_req <&#61; 1&#39;b0;
always &#64;(posedge clk or negedge rst)
if(!rst)
write_data <&#61; 8&#39;d0;
else if(next_write_state &#61;&#61; 2&#39;b01)
write_data <&#61; write_data &#43; 1&#39;b1;

// read_state and next_read_state
reg[1:0] read_state;
reg[1:0] next_read_state;
always&#64;(posedge clk or negedge rst)
if(!rst)
read_state <&#61; 2&#39;b00;
else
read_state <&#61; next_read_state;

always&#64;(*)
if(!rst)
next_read_state <&#61; 2&#39;b00;
else begin
case (read_state)
2&#39;b00:
if(!read_empty)
next_read_state <&#61; 2&#39;b01;
else
next_read_state <&#61; 2&#39;b00;

2&#39;b01:
if(read_empty)
next_read_state <&#61; 2&#39;b00;
else
next_read_state <&#61; 2&#39;b01;

default:
next_read_state <&#61; 2&#39;b00;
endcase
end
always &#64;(posedge clk or negedge rst)
if(!rst)
read_req <&#61; 1&#39;b0;
else if(next_read_state &#61;&#61; 2&#39;b01)
read_req <&#61; 1&#39;b1;
else
read_req <&#61; 1&#39;b0;
// invoke ip ip_fifo
wire[7:0] rdusedw;
wire[7:0] wrusedw;
ip_fifo ip_fifo0(
.data(write_data),
.rdclk(clk),
.rdreq(read_req),
.wrclk(clk),
.wrreq(write_req),
.q(read_data),
.rdempty(read_empty),
.rdusedw(rdusedw),
.wrfull(write_full),
.wrusedw(wrusedw));
endmodule

         测试代码的内容不复杂&#xff0c;主要的工作就是把流程切分成write_state和read_state。对于write_state而言&#xff0c;一旦发现fifo不满&#xff0c;就开始写入数据。而对于read_state而言&#xff0c;每当发现fifo非空&#xff0c;就不停读取数据。这样&#xff0c;一写一读&#xff0c;就构成了fifo的基本操作。如果两者速率不匹配&#xff0c;或者字节长度不同&#xff0c;fifo还可以充当临时buffer的角色。当然&#xff0c;为了验证我们的测试是否正确&#xff0c;最终还得借助于SignalTap这个工具。


c&#xff09;SignalTap配置和测试

        SignalTap中主要检查写入和读取的数据&#xff0c;

        烧入sof文件之后&#xff0c;经过F6和Esc之后&#xff0c;就可以看到相关的波形数据了&#xff0c;

 


补充1&#xff1a;

        之前测试的时候一直没有注意时序约束。事实上&#xff0c;在 fpga开发过程中最好做到0 error&#xff0c;0 warning。这是比较合适的。所以&#xff0c;项目中最好添加必要的时序约束文件&#xff0c;告知quartus软件当前fpga希望以什么样的时钟运行&#xff0c;

# Clock constraints
create_clock -name "clk" -period 20.000ns [get_ports clk]
# Automatically constrain PLL and other generated clocks
derive_pll_clocks -create_base_clocks
# Automatically calculate clock uncertainty to jitter and other effects.
derive_clock_uncertainty
# tsu/th constraints
# tco constraints
# tpd constraints

补充2&#xff1a;

        另外&#xff0c;如果引脚比较多&#xff0c;pin bind也是一个体力活。这部分可以借助于tcl脚本来完成。编写完tcl之后&#xff0c;就可以通过"Tools"->"Tcl Scripts"运行脚本即可&#xff0c;

package require ::quartus::project
set_location_assignment PIN_E1 -to clk
set_location_assignment PIN_N13 -to rst
set_location_assignment PIN_D9 -to led[3]
set_location_assignment PIN_C9 -to led[2]
set_location_assignment PIN_F9 -to led[1]
set_location_assignment PIN_E10 -to led[0]


推荐阅读
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • 本文介绍了九度OnlineJudge中的1002题目“Grading”的解决方法。该题目要求设计一个公平的评分过程,将每个考题分配给3个独立的专家,如果他们的评分不一致,则需要请一位裁判做出最终决定。文章详细描述了评分规则,并给出了解决该问题的程序。 ... [详细]
  • Metasploit攻击渗透实践
    本文介绍了Metasploit攻击渗透实践的内容和要求,包括主动攻击、针对浏览器和客户端的攻击,以及成功应用辅助模块的实践过程。其中涉及使用Hydra在不知道密码的情况下攻击metsploit2靶机获取密码,以及攻击浏览器中的tomcat服务的具体步骤。同时还讲解了爆破密码的方法和设置攻击目标主机的相关参数。 ... [详细]
  • 本文介绍了Oracle数据库中tnsnames.ora文件的作用和配置方法。tnsnames.ora文件在数据库启动过程中会被读取,用于解析LOCAL_LISTENER,并且与侦听无关。文章还提供了配置LOCAL_LISTENER和1522端口的示例,并展示了listener.ora文件的内容。 ... [详细]
  • 本文介绍了Hyperledger Fabric外部链码构建与运行的相关知识,包括在Hyperledger Fabric 2.0版本之前链码构建和运行的困难性,外部构建模式的实现原理以及外部构建和运行API的使用方法。通过本文的介绍,读者可以了解到如何利用外部构建和运行的方式来实现链码的构建和运行,并且不再受限于特定的语言和部署环境。 ... [详细]
  • 本文介绍了Perl的测试框架Test::Base,它是一个数据驱动的测试框架,可以自动进行单元测试,省去手工编写测试程序的麻烦。与Test::More完全兼容,使用方法简单。以plural函数为例,展示了Test::Base的使用方法。 ... [详细]
  • Go Cobra命令行工具入门教程
    本文介绍了Go语言实现的命令行工具Cobra的基本概念、安装方法和入门实践。Cobra被广泛应用于各种项目中,如Kubernetes、Hugo和Github CLI等。通过使用Cobra,我们可以快速创建命令行工具,适用于写测试脚本和各种服务的Admin CLI。文章还通过一个简单的demo演示了Cobra的使用方法。 ... [详细]
  • 本文讨论了在openwrt-17.01版本中,mt7628设备上初始化启动时eth0的mac地址总是随机生成的问题。每次随机生成的eth0的mac地址都会写到/sys/class/net/eth0/address目录下,而openwrt-17.01原版的SDK会根据随机生成的eth0的mac地址再生成eth0.1、eth0.2等,生成后的mac地址会保存在/etc/config/network下。 ... [详细]
  • 本文讨论了在手机移动端如何使用HTML5和JavaScript实现视频上传并压缩视频质量,或者降低手机摄像头拍摄质量的问题。作者指出HTML5和JavaScript无法直接压缩视频,只能通过将视频传送到服务器端由后端进行压缩。对于控制相机拍摄质量,只有使用JAVA编写Android客户端才能实现压缩。此外,作者还解释了在交作业时使用zip格式压缩包导致CSS文件和图片音乐丢失的原因,并提供了解决方法。最后,作者还介绍了一个用于处理图片的类,可以实现图片剪裁处理和生成缩略图的功能。 ... [详细]
  • 本文介绍了如何使用Express App提供静态文件,同时提到了一些不需要使用的文件,如package.json和/.ssh/known_hosts,并解释了为什么app.get('*')无法捕获所有请求以及为什么app.use(express.static(__dirname))可能会提供不需要的文件。 ... [详细]
  • 本文介绍了如何在给定的有序字符序列中插入新字符,并保持序列的有序性。通过示例代码演示了插入过程,以及插入后的字符序列。 ... [详细]
  • Android Studio Bumblebee | 2021.1.1(大黄蜂版本使用介绍)
    本文介绍了Android Studio Bumblebee | 2021.1.1(大黄蜂版本)的使用方法和相关知识,包括Gradle的介绍、设备管理器的配置、无线调试、新版本问题等内容。同时还提供了更新版本的下载地址和启动页面截图。 ... [详细]
  • 不同优化算法的比较分析及实验验证
    本文介绍了神经网络优化中常用的优化方法,包括学习率调整和梯度估计修正,并通过实验验证了不同优化算法的效果。实验结果表明,Adam算法在综合考虑学习率调整和梯度估计修正方面表现较好。该研究对于优化神经网络的训练过程具有指导意义。 ... [详细]
  • Android开发实现的计时器功能示例
    本文分享了Android开发实现的计时器功能示例,包括效果图、布局和按钮的使用。通过使用Chronometer控件,可以实现计时器功能。该示例适用于Android平台,供开发者参考。 ... [详细]
  • WhenIusepythontoapplythepymysqlmoduletoaddafieldtoatableinthemysqldatabase,itdo ... [详细]
author-avatar
剪子61_199
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有